import javax.swing.JFrame;
import cii_lib.CIIdata;
 
public abstract class AccessMode
{
	public abstract void Init();
	public abstract void Configure(String key, String value);
	public abstract void configDialog(JFrame parentFrame);
	public abstract void Connect() throws AccessModeException;
	public abstract void Disconnect() throws AccessModeException;
	public abstract long Read(long address) throws AccessModeException;
	public abstract void Write(long address,long data) throws AccessModeException;
	public abstract String getModeName();
	public abstract String getDescription();
	
	// skopiowane z jserver.java:
	private int _AreaSize(int num){
		if ((num--)==0) return(0);
		int cnt=1;
		while(num>1){
		  num/=2;
		  cnt++;
		}
		return(1<<cnt);
	}
	
	public void writeBit(int data_width, int width, int numbers, int groups, long addr, int num_pos, int grp_pos, int bpos, CIIdata data) throws AccessModeException
	{
	    if (data_width<=0 || width<=0 || numbers<=0 || groups<=0 || addr<0 || num_pos<0 || grp_pos<0 || bpos<0 || numbers<=num_pos || groups<=grp_pos || width*numbers*groups>data_width) throw new AccessModeException("Bad parameters!"); 
	      if (width==0 || numbers==0 || groups==0) return;
	      int Pos = (grp_pos*numbers + num_pos)*width+bpos;
	      long Res = Read(addr);
	      Res = (Res & (~(((1<<width)-1)<<Pos))) | (data.GetValue()<<Pos);
	      Write(addr,Res);
	}
	
	public void writeWord(int data_width, int width, int numbers, int groups, long addr, int num_pos,int grp_pos, CIIdata data) throws AccessModeException
	{
	    if (data_width<=0 || width<=0 || numbers<=0 || groups<=0 || addr<0 || num_pos<0 || grp_pos<0 || numbers<=num_pos || groups<=grp_pos)
	        throw new AccessModeException("Bad parameters!");
		if (width==0 || numbers==0 || groups==0) return;
		int PartNum = (width-1)/data_width+1;
		int LastWidth = width-(width/data_width)*data_width;
		long PartAddr = addr + PartNum*(grp_pos*numbers + num_pos);
		for(int index=0; index<PartNum; index++)
			if (index+1<PartNum || LastWidth==0)
				Write(PartAddr+index,data.GetValue(index*data_width,data_width));
			else
				Write(PartAddr+index,data.GetValue(index*data_width,LastWidth));
	}
	
	public void writeArea(int data_width, int width, int numbers, int groups, long addr, int num_pos,int grp_pos, CIIdata data) throws AccessModeException
	{
	    if (data_width<=0 || width<=0 || numbers<=0 || groups<=0 || addr<0 || num_pos<0 || grp_pos<0 || numbers<=num_pos || groups<=grp_pos) throw new AccessModeException("Bad parameters!");
	      if (width==0 || numbers==0 || groups==0) return;
	      int PartNum = (width-1)/data_width+1;
	      int LastWidth = width-(width/data_width)*data_width;
	      int AreaWidth=_AreaSize(numbers);
	      long PartAddr = addr + grp_pos*AreaWidth*PartNum + num_pos;
	      for(int index=0; index<PartNum; index++)
	        if (index+1<PartNum || LastWidth==0)
	          Write(PartAddr+index*AreaWidth,data.GetValue(index*data_width,data_width));
	        else
	          Write(PartAddr+index*AreaWidth,data.GetValue(index*data_width,LastWidth));
	}
	
	public CIIdata readBit(int data_width, int width, int numbers, int groups, long addr, int num_pos, int grp_pos, int bpos, CIIdata data) throws AccessModeException
	{
	    if (data_width<=0 || width<=0 || numbers<=0 || groups<=0 || addr<0 || num_pos<0 || grp_pos<0 || bpos<0 || numbers<=num_pos || groups<=grp_pos || width*numbers*groups>data_width) throw new AccessModeException("Bad parameters!");
	      if (width==0 || numbers==0 || groups==0) return(null);
	      CIIdata Res = data==null ? new CIIdata(width) : data;
	      int Pos = (grp_pos*numbers + num_pos)*width+bpos;
	      long Val = Read(addr);
	      Val = (Val>>Pos) & ((1<<width)-1);
	      Res.SetValue(0,width,Val);
	      return(Res);
	}
	
	public CIIdata readWord(int data_width, int width, int numbers, int groups, long addr, int num_pos,int grp_pos, CIIdata data) throws AccessModeException
	{
	    if (data_width<=0 || width<=0 || numbers<=0 || groups<=0 || addr<0 || num_pos<0 || grp_pos<0 || numbers<=num_pos || groups<=grp_pos) throw new AccessModeException("Bad parameters!");
	      if (width==0 || numbers==0 || groups==0) return(null);
	      CIIdata Res = data==null ? new CIIdata(width) : data;
	      int PartNum = (width-1)/data_width+1;
	      int LastWidth = width-(width/data_width)*data_width;
	      long PartAddr = addr + PartNum*(grp_pos*numbers + num_pos);
	      long Data;
	      for(int index=0; index<PartNum; index++)
	        if (index+1<PartNum || LastWidth==0){
	  	Data=Read(PartAddr+index);
	          Res.SetValue(index*data_width,data_width,Data);
	        }
	        else{
	  	Data=Read(PartAddr+index);
	          Res.SetValue(index*data_width,LastWidth,Data);
	        }
	      return (Res);
	}
	
	public CIIdata readArea(int data_width, int width, int numbers, int groups, long addr, int num_pos,int grp_pos, CIIdata data) throws AccessModeException
	{
	    if (data_width<=0 || width<=0 || numbers<=0 || groups<=0 || addr<0 || num_pos<0 || grp_pos<0 || numbers<=num_pos || groups<=grp_pos) throw new AccessModeException("Bad parameters!");
	    CIIdata Res = data==null ? new CIIdata(width) : data;
	    int PartNum = (width-1)/data_width+1;
	    int LastWidth = width-(width/data_width)*data_width;
	    int AreaWidth=_AreaSize(numbers);
	    long PartAddr = addr + grp_pos*AreaWidth*PartNum + num_pos;
	    long Data;
	    for(int index=0; index<PartNum; index++)
	        if (index+1<PartNum || LastWidth==0){
	          Data=Read(PartAddr+index*AreaWidth);
	          Res.SetValue(index*data_width,data_width,Data);
	        }
	        else{
	          Data=Read(PartAddr+index*AreaWidth);
	          Res.SetValue(index*data_width,LastWidth,Data);
	        }
	      return (Res);
	}
}
